#ifndef __MY_UTIL_H__
#define __MY_UTIL_H__
#include <jsoncpp/json/json.h>
#include <string>
#include <memory>
#include <sstream>
#include <fstream>
#include <vector>
#include "Log.hpp"
#include <sodium.h>
#include <websocketpp/server.hpp>
#include <websocketpp/config/asio_no_tls.hpp>

using namespace LogModule;

using ws_server_t = websocketpp::server<websocketpp::config::asio>;
using http_status_t = websocketpp::http::status_code::value;
using id_t = uint32_t;

class Util_Json
{
public:
    // 序列化
    static bool Serialize(const Json::Value &root, std::string &json_str)
    {
        Json::StreamWriterBuilder swb;
        // 启用UTF-8直接输出（不转义非ASCII字符）
        swb.settings_["emitUTF8"] = true;
        std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());

        std::stringstream ss;
        int ret = sw->write(root, &ss);
        if (ret != 0)
        {
            LOG(LogLevel::ERROR) << "序列化失败!";
            return false;
        }
        json_str = ss.str();
        return true;
    }
    // 反序列化
    static bool Deserialize(const std::string &json_str, Json::Value &root)
    {
        Json::CharReaderBuilder crb;
        std::unique_ptr<Json::CharReader> cr(crb.newCharReader());

        std::string err;
        bool ret = cr->parse(json_str.c_str(), json_str.c_str() + json_str.size(), &root, &err);
        if (!ret)
        {
            LOG(LogLevel::ERROR) << "反序列化失败: " << err;
            return false;
        }
        return true;
    }
};

class Util_String
{
public:
    // 字符串分割
    static size_t Split(const std::string &str, const std::string &sep, std::vector<std::string> &res)
    {
        res.clear(); // 清空原有内容，确保结果仅包含本次分割的元素
        if (sep.empty())
        {
            return 0;
        }

        const size_t sep_len = sep.size();
        const size_t str_len = str.size();
        size_t index = 0;
        while (index < str_len)
        {
            size_t pos = str.find(sep, index);
            // 未找到分隔符，截取剩余部分
            if (pos == std::string::npos)
            {
                res.emplace_back(str.substr(index));
                break;
            }
            // 当前位置就是分隔符，跳过
            if (pos == index)
            {
                index += sep_len;
                continue;
            }
            // 截取[index, pos)区间的子串
            res.emplace_back(str.substr(index, pos - index));
            index = pos + sep_len;
        }
        return res.size();
    }
};

class Util_File
{
public:
    static bool Read(const std::string &filename, std::string &body)
    {
        // 打开文件
        std::ifstream ifs(filename, std::ios::binary);
        if (!ifs.is_open())
        {
            LOG(LogLevel::ERROR) << "[" << filename << "]文件打开失败!";
            return false;
        }

        // 获取文件大小
        ifs.seekg(0, std::ifstream::end);
        size_t fsize = ifs.tellg();
        ifs.seekg(0, std::ifstream::beg);
        body.resize(fsize);

        // 读取文件
        ifs.read(&body[0], fsize);
        if (!ifs.good())
        {
            ifs.close();
            LOG(LogLevel::ERROR) << "[" << filename << "]读取文件失败";
            return false;
        }

        // 关闭文件
        ifs.close();
        return true;
    }
};

class Util_Hash
{
public:
    static bool Init()
    {
        if (sodium_init() < 0)
        {
            LOG(LogLevel::ERROR) << "libsodium初始化失败!";
            return false;
        }
        return true;
    }

    // 生成密码哈希（存储到数据库）
    static std::string Password(const std::string &password)
    {
        // 哈希结果缓冲区（包含盐值和哈希值，可直接存储）
        std::vector<char> hash(crypto_pwhash_STRBYTES);

        // 加密参数（libsodium推荐的安全值，可根据性能调整）
        const unsigned long long opslimit = crypto_pwhash_OPSLIMIT_MODERATE; // 计算次数
        const size_t memlimit = crypto_pwhash_MEMLIMIT_MODERATE;             // 内存限制

        // 生成哈希（自动生成随机盐值，并存入hash中）
        if (crypto_pwhash_str(
                hash.data(),
                password.c_str(),
                password.size(),
                opslimit,
                memlimit) != 0)
        {
            throw std::runtime_error("密码哈希失败（可能内存不足）");
        }

        return std::string(hash.data());
    }

    // 验证密码（对比用户输入与存储的哈希）
    static bool Verify(const std::string &password, const std::string &stored_hash)
    {
        // 验证哈希是否匹配
        return crypto_pwhash_str_verify(
                   stored_hash.c_str(),
                   password.c_str(),
                   password.size()) == 0;
    }
};

#endif